home *** CD-ROM | disk | FTP | other *** search
/ Aminet 23 / Aminet 23 (1998)(GTI - Schatztruhe)[!][Feb 1998].iso / Aminet / misc / emu / amiSPIMsrc.lha / data.c < prev    next >
C/C++ Source or Header  |  1994-01-17  |  8KB  |  437 lines

  1. /* SPIM S20 MIPS simulator.
  2.    Code to manipulate data segment directives.
  3.    Copyright (C) 1990-1994 by James Larus (larus@cs.wisc.edu).
  4.    ALL RIGHTS RESERVED.
  5.  
  6.    SPIM is distributed under the following conditions:
  7.  
  8.      You may make copies of SPIM for your own use and modify those copies.
  9.  
  10.      All copies of SPIM must retain my name and copyright notice.
  11.  
  12.      You may not sell SPIM or distributed SPIM in conjunction with a
  13.      commerical product or service without the expressed written consent of
  14.      James Larus.
  15.  
  16.    THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.    IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19.    PURPOSE. */
  20.  
  21.  
  22. /* $Header: /home/primost/larus/Software/SPIM/RCS/data.c,v 3.12 1994/01/18 03:21:45 larus Exp larus $
  23. */
  24.  
  25.  
  26. #include "spim.h"
  27. #include "spim-utils.h"
  28. #include "inst.h"
  29. #include "mem.h"
  30. #include "reg.h"
  31. #include "sym-tbl.h"
  32. #include "parser.h"
  33. #include "run.h"
  34. #include "read-aout.h"
  35. #include "data.h"
  36.  
  37.  
  38. /* The first 64K of the data segment are dedicated to small data
  39.    segment, which is pointed to by $gp. This register points to the
  40.    middle of the segment, so we can use the full offset field in an
  41.    instruction. */
  42.  
  43. static mem_addr next_data_pc;    /* Location for next datum in user process */
  44.  
  45. static mem_addr next_k_data_pc;    /* Location for next datum in kernel */
  46.  
  47. static int in_kernel = 0;    /* Non-zero => data goes to kdata, not data */
  48.  
  49. #define DATA_PC (in_kernel ? next_k_data_pc : next_data_pc)
  50.  
  51. #define BUMP_DATA_PC(DELTA) {if (in_kernel) \
  52.                 next_k_data_pc += DELTA; \
  53.                 else {next_data_pc += DELTA; \
  54.                       program_break = next_data_pc;}}
  55.  
  56. static int next_gp_offset;    /* Offset off $gp of next data item */
  57.  
  58. static int auto_alignment = 1;    /* Non-zero => align literal to natural bound*/
  59.  
  60.  
  61.  
  62. /* If TO_KERNEL is non-zero, subsequent data will be placed in the
  63.    kernel data segment.  If it is zero, data will go to the user's data
  64.    segment.*/
  65.  
  66. #ifdef __STDC__
  67. void
  68. user_kernel_data_segment (int to_kernel)
  69. #else
  70. void
  71. user_kernel_data_segment (to_kernel)
  72. int to_kernel;
  73. #endif
  74. {
  75.     in_kernel = to_kernel;
  76. }
  77.  
  78.  
  79. #ifdef __STDC__
  80. void
  81. end_of_assembly_file (void)
  82. #else
  83. void
  84. end_of_assembly_file ()
  85. #endif
  86. {
  87.   in_kernel = 0;
  88.   auto_alignment = 1;
  89. }
  90.  
  91.  
  92. /* Set the point at which the first datum is stored to be ADDRESS +
  93.    64K.     The 64K increment allocates an area pointed to by register
  94.    $gp, which is initialized. */
  95.  
  96. #ifdef __STDC__
  97. void
  98. data_begins_at_point (mem_addr addr)
  99. #else
  100. void
  101. data_begins_at_point (addr)
  102.      mem_addr addr;
  103. #endif
  104. {
  105.   if (bare_machine)
  106.     next_data_pc = addr;
  107.   else
  108.     {
  109.       next_gp_offset = addr;
  110.       gp_midpoint = addr + 32*K;
  111.       R[REG_GP] = gp_midpoint;
  112.       next_data_pc = addr + 64 * K;
  113.     }
  114. }
  115.  
  116.  
  117. /* Set the point at which the first datum is stored in the kernel's
  118.    data segment. */
  119.  
  120. #ifdef __STDC__
  121. void
  122. k_data_begins_at_point (mem_addr addr)
  123. #else
  124. void
  125. k_data_begins_at_point (addr)
  126.      mem_addr addr;
  127. #endif
  128. {
  129.     next_k_data_pc = addr;
  130. }
  131.  
  132.  
  133. /* Arrange that the next datum is stored on a memory boundary with its
  134.    low ALIGNMENT bits equal to 0.  If argument is 0, disable automatic
  135.    alignment.*/
  136.  
  137. #ifdef __STDC__
  138. void
  139. align_data (int alignment)
  140. #else
  141. void
  142. align_data (alignment)
  143.      int alignment;
  144. #endif
  145. {
  146.   if (alignment == 0)
  147.     auto_alignment = 0;
  148.   else if (in_kernel)
  149.     {
  150.       next_k_data_pc =
  151.     (next_k_data_pc + (1 << alignment) - 1) & (-1 << alignment);
  152.       fix_current_label_address (next_k_data_pc);
  153.     }
  154.   else
  155.     {
  156.       next_data_pc = (next_data_pc + (1 << alignment) - 1) & (-1 << alignment);
  157.       fix_current_label_address (next_data_pc);
  158.     }
  159. }
  160.  
  161.  
  162. #ifdef __STDC__
  163. void
  164. set_data_alignment (int alignment)
  165. #else
  166. void
  167. set_data_alignment (alignment)
  168.      int alignment;
  169. #endif
  170. {
  171.   if (auto_alignment)
  172.     align_data (alignment);
  173. }
  174.  
  175.  
  176. #ifdef __STDC__
  177. void
  178. enable_data_alignment (void)
  179. #else
  180. void
  181. enable_data_alignment ()
  182. #endif
  183. {
  184.   auto_alignment = 1;
  185. }
  186.  
  187.  
  188. /* Set the location (in user or kernel data space) for the next datum. */
  189.  
  190. #ifdef __STDC__
  191. void
  192. set_data_pc (mem_addr addr)
  193. #else
  194. void
  195. set_data_pc (addr)
  196.      mem_addr addr;
  197. #endif
  198. {
  199.   if (in_kernel)
  200.     next_k_data_pc = addr;
  201.   else
  202.     next_data_pc = addr;
  203. }
  204.  
  205.  
  206. /* Return the address at which the next datum will be stored.  */
  207.  
  208. #ifdef __STDC__
  209. mem_addr
  210. current_data_pc (void)
  211. #else
  212. mem_addr
  213. current_data_pc ()
  214. #endif
  215. {
  216.   return (DATA_PC);
  217. }
  218.  
  219.  
  220. /* Bump the address at which the next data will be stored by VALUE
  221.    bytes. */
  222.  
  223. #ifdef __STDC__
  224. void
  225. increment_data_pc (int value)
  226. #else
  227. void
  228. increment_data_pc (value)
  229.      int value;
  230. #endif
  231. {
  232.   BUMP_DATA_PC (value);
  233. }
  234.  
  235.  
  236. /* Process a .extern NAME SIZE directive. */
  237.  
  238. #ifdef __STDC__
  239. void
  240. extern_directive (char *name, int size)
  241. #else
  242. void
  243. extern_directive (name, size)
  244.      char *name;
  245.      int size;
  246. #endif
  247. {
  248.   label *sym = make_label_global (name);
  249.  
  250.   if (!bare_machine
  251.       && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE
  252.       && next_gp_offset + size < gp_midpoint + 32*K)
  253.     {
  254.       sym->gp_flag = 1;
  255.       sym->addr = next_gp_offset;
  256.       next_gp_offset += size;
  257.     }
  258. }
  259.  
  260.  
  261. /* Process a .lcomm NAME SIZE directive. */
  262.  
  263. #ifdef __STDC__
  264. void
  265. lcomm_directive (char *name, int size)
  266. #else
  267. void
  268. lcomm_directive (name, size)
  269.      char *name;
  270.      int size;
  271. #endif
  272. {
  273.   label *sym = lookup_label (name);
  274.  
  275.   if (!bare_machine
  276.       && size > 0 && size <= SMALL_DATA_SEG_MAX_SIZE
  277.       && next_gp_offset + size < gp_midpoint + 32*K)
  278.     {
  279.       sym->gp_flag = 1;
  280.       sym->addr = next_gp_offset;
  281.       next_gp_offset += size;
  282.     }
  283.   /* Don't need to initialize since memory starts with 0's */
  284. }
  285.  
  286.  
  287. /* Process a .ascii STRING or .asciiz STRING directive. */
  288.  
  289. #ifdef __STDC__
  290. void
  291. store_string (char *string, int length, int null_terminate)
  292. #else
  293. void
  294. store_string (string, length, null_terminate)
  295.      char *string;
  296.      int length;
  297.      int null_terminate;
  298. #endif
  299. {
  300.   for ( ; length > 0; string ++, length --) {
  301.     SET_MEM_BYTE (DATA_PC, *string);
  302.     BUMP_DATA_PC(1);
  303.   }
  304.   if (null_terminate)
  305.     {
  306.       SET_MEM_BYTE (DATA_PC, 0);
  307.       BUMP_DATA_PC(1);
  308.     }
  309. }
  310.  
  311.  
  312. /* Process a .byte EXPR directive. */
  313.  
  314. #ifdef __STDC__
  315. void
  316. store_byte (int value)
  317. #else
  318. void
  319. store_byte (value)
  320.      int value;
  321. #endif
  322. {
  323.   SET_MEM_BYTE (DATA_PC, value);
  324.   BUMP_DATA_PC (1);
  325. }
  326.  
  327.  
  328. /* Process a .half EXPR directive. */
  329.  
  330. #ifdef __STDC__
  331. void
  332. store_half (int value)
  333. #else
  334. void
  335. store_half (value)
  336.      int value;
  337. #endif
  338. {
  339.   if (DATA_PC & 0x1)
  340.     {
  341. #ifdef BIGENDIAN
  342.       store_byte ((value >> 8) & 0xff);
  343.       store_byte (value & 0xff);
  344. #else
  345.       store_byte (value & 0xff);
  346.       store_byte ((value >> 8) & 0xff);
  347. #endif
  348.     }
  349.   else
  350.     {
  351.       SET_MEM_HALF (DATA_PC, value);
  352.       BUMP_DATA_PC (BYTES_PER_WORD / 2);
  353.     }
  354. }
  355.  
  356.  
  357. /* Process a .word EXPR directive. */
  358.  
  359. #ifdef __STDC__
  360. void
  361. store_word (int value)
  362. #else
  363. void
  364. store_word (value)
  365.      int value;
  366. #endif
  367. {
  368.   if (DATA_PC & 0x3)
  369.     {
  370. #ifdef BIGENDIAN
  371.       store_half ((value >> 16) & 0xffff);
  372.       store_half (value & 0xffff);
  373. #else
  374.       store_half (value & 0xffff);
  375.       store_half ((value >> 16) & 0xffff);
  376. #endif
  377.     }
  378.   else
  379.     {
  380.       SET_MEM_WORD (DATA_PC, value);
  381.       BUMP_DATA_PC (BYTES_PER_WORD);
  382.     }
  383. }
  384.  
  385.  
  386. /* Process a .double EXPR directive. */
  387.  
  388. #ifdef __STDC__
  389. void
  390. store_double (double *value)
  391. #else
  392. void
  393. store_double (value)
  394.      double *value;
  395. #endif
  396. {
  397.   if (DATA_PC & 0x7)
  398.     {
  399.       store_word (* ((long *) value));
  400.       store_word (* (((long *) value) + 1));
  401.     }
  402.   else
  403.     {
  404.       SET_MEM_WORD (DATA_PC, * ((long *) value));
  405.       BUMP_DATA_PC (BYTES_PER_WORD);
  406.       SET_MEM_WORD (DATA_PC, * (((long *) value) + 1));
  407.       BUMP_DATA_PC (BYTES_PER_WORD);
  408.     }
  409. }
  410.  
  411.  
  412. /* Process a .float EXPR directive. */
  413.  
  414. #ifdef __STDC__
  415. void
  416. store_float (double *value)
  417. #else
  418. void
  419. store_float (value)
  420.      double *value;
  421. #endif
  422. {
  423.   float val = *value;
  424.   float *vp = &val;
  425.  
  426.   if (DATA_PC & 0x3)
  427.     {
  428.       store_half (*(long *) vp & 0xffff);
  429.       store_half ((*(long *) vp >> 16) & 0xffff);
  430.     }
  431.   else
  432.     {
  433.       SET_MEM_WORD (DATA_PC, *((long *) vp));
  434.       BUMP_DATA_PC (BYTES_PER_WORD);
  435.     }
  436. }
  437.